import time
from threading import Thread

import requests
from PySide6.QtWidgets import (QHBoxLayout, QVBoxLayout, QApplication, QFrame, QLabel, QPushButton, QPlainTextEdit,
                               QMainWindow, QWidget, QLineEdit, QFormLayout, QGridLayout, QTextEdit, QMessageBox,
                               QComboBox, QTableWidget, QTableWidgetItem, QSizePolicy, )
from PySide6.QtCore import Qt, QSize, QObject, Signal
from PySide6.QtGui import QIcon
import icon

'''
界面分上中下3部分（垂直布局）
上部：
（水平布局）请求方式-下拉选择；单行输入框，提示底纹（请输入url）；“发送”按钮，支持点击和回车发送请求

中部：
-（水平布局）
----消息头：
-------（水平布局）支持增减；
-------（表格布局）名称：值
----消息体：
-------（垂直布局）支持多行输入

下部：
（垂直布局）  多文本输入框，只读模式；清除按钮，点击后清除文本框中的内容
'''


class MySingle(QObject):
    response_print = Signal(QPlainTextEdit, str)
    response_finish = Signal()
    response_start = Signal()


class HttpRequestTool(QMainWindow):
    def __init__(self):
        super().__init__()
        self.resize(800, 600)
        self.global_ms = MySingle()  # 创建一个自定义信号的实例

        # 创建主窗口
        main_widget = QWidget(self)
        self.setCentralWidget(main_widget)

        # 创建垂直布局为主窗口布局
        main_vl = QVBoxLayout(main_widget)
        ############################################################################################
        # 上部，（水平布局）
        upper_hl = QHBoxLayout()
        main_vl.addLayout(upper_hl)  # 添加到上部水平布局中

        # 请求方式-下拉选择；
        self.request_method = QComboBox()
        upper_hl.addWidget(self.request_method)
        self.request_method.addItems(['GET', 'POST', 'PUT', 'DELETE'])
        self.method_info = 'GET'  # 设置默认的请求方式

        # 单行输入框，提示底纹（请输入url）；
        self.input_url = QLineEdit()
        upper_hl.addWidget(self.input_url)
        self.input_url.setPlaceholderText('请输入url (如: http://127.0.0.1/api/mgr/signin)')
        self.url_info = ''  # 设置url的初始状态

        # “发送”按钮，支持点击和回车发送请求
        self.whole_request = requests.Session()  # 保存cookie信息
        self.send_request_button = QPushButton('发送')
        upper_hl.addWidget(self.send_request_button)
        self.send_request_button.clicked.connect(self.create_thread)  # 连接发出请求函数
        ############################################################################################
        # 中部，水平布局
        centre_hl = QHBoxLayout()
        main_vl.addLayout(centre_hl)
        # 中部的左半部分，垂直布局

        centre_left_vl = QVBoxLayout()
        centre_hl.addLayout(centre_left_vl)
        # 消息头，水平布局

        message_head_hl = QHBoxLayout()
        centre_left_vl.addLayout(message_head_hl)
        message_head_hl.addWidget(QLabel('消息头'))

        # 加减按钮
        self.minus_button = QPushButton('-')
        self.add_button = QPushButton('+')
        message_head_hl.addWidget(self.minus_button)
        message_head_hl.addWidget(self.add_button)
        self.add_button.clicked.connect(self.add_argument)
        self.minus_button.clicked.connect(self.minus_argument)

        # 中部的右边那部分，垂直布局
        centre_right_vl = QVBoxLayout()
        centre_hl.addLayout(centre_right_vl)

        # 消息体标题
        centre_right_vl.addWidget(QLabel('消息体'))

        # 消息体多行文本框
        self.message_body = QPlainTextEdit()
        self.message_body.setPlaceholderText("格式: key1=value1&key2=value2")
        centre_right_vl.addWidget(self.message_body)

        # 消息头表格输入框
        self.request_arguments_table = QTableWidget(3, 2)  # 创建3行2列的表格
        centre_left_vl.addWidget(self.request_arguments_table)
        self.request_arguments_table.setHorizontalHeaderLabels(['名称', '值'])
        self.request_arguments_table.setItem(0, 0, QTableWidgetItem('timestamp'))
        self.request_arguments_table.setItem(0, 1, QTableWidgetItem('20250727'))
        self.request_arguments_table.setItem(1, 0, QTableWidgetItem('content-type'))
        self.request_arguments_table.setItem(1, 1, QTableWidgetItem('application/x-www-form-urlencoded; charset=UTF-8'))
        self.request_arguments_table.setItem(2, 0, QTableWidgetItem('user-agent'))
        self.request_arguments_table.setItem(2, 1, QTableWidgetItem(
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36'))
        ############################################################################################
        # 下部，垂直布局
        below_vl = QVBoxLayout()
        main_vl.addLayout(below_vl)

        # 展示接口返回的数据，多文本框，标题
        below_vl.addWidget(QLabel('响应结果:'))
        self.send_return_message = QPlainTextEdit()
        self.send_return_message.setReadOnly(True)  # 设置为只读模式
        below_vl.addWidget(self.send_return_message)

        # 清楚文本框中的信息按钮, 新增一个拖拽按钮，设置水平布局
        below_button_hl = QHBoxLayout()
        below_vl.addLayout(below_button_hl)
        self.clean_message = QPushButton('清除响应结果')
        self.pull_push_message = QPushButton('拖拽按钮')
        self.clean_message.setFixedSize(120, 35)
        self.pull_push_message.setFixedSize(600, 35)
        below_button_hl.addWidget(self.clean_message)
        below_button_hl.addWidget(self.pull_push_message)
        below_button_hl.addStretch()
        # below_button_hl.addWidget(self.clean_message, alignment=Qt.AlignCenter)  # 设置居中
        self.clean_message.clicked.connect(self.send_return_message.clear)  #连接清除函数

        # 连接信号，处理更新url，method, 消息头数据
        self.input_url.textChanged.connect(self.url_change)  # url
        self.request_method.currentIndexChanged.connect(self.method_change)  # 请求方法
        self.request_arguments_table.cellChanged.connect(self.update_message_head)  # 实时检测表格的增删改状态，获取最新的数据
        # 使用多线程消息处理主线程的信息
        self.global_ms.response_start.connect(self.response_start)
        self.global_ms.response_finish.connect(self.response_finished)
        self.global_ms.response_print.connect(self.response_show)
        # 获取选中文本的信号
        # self.input_url.selectionChanged.connect()
        # 重置“拖拽”按钮的名字
        self.pull_push_message.clicked.connect(self.get_slelect_text)

    ###############   处理url数据，method信息###########################################
    def method_change(self):
        self.method_info = self.request_method.currentText()  # 获取下拉中的数据，请求的方法
        print(f'更新请求方法为{self.method_info}')

    def url_change(self):
        self.url_info = self.input_url.text()  # 获取输入框中的url信息
        print(f'更新url为{self.url_info}')

    ################   处理消息头，消息体数据   ######################################################
    def response_show(self, editor, text):
        editor.setPlainText(str(text))

    # 启动发送按钮
    def response_finished(self):
        self.send_request_button.setEnabled(True)

    # 置灰发送按钮
    def response_start(self):
        self.send_request_button.setEnabled(False)

    def add_argument(self):
        row_numb = self.request_arguments_table.rowCount()
        self.request_arguments_table.insertRow(row_numb)
        print('新增一行')

    def minus_argument(self):
        choice_num = self.request_arguments_table.currentRow()
        if choice_num >= 0:
            self.request_arguments_table.removeRow(choice_num)
            self.update_message_head()

    def update_message_head(self):
        headers = {}
        row_numb = self.request_arguments_table.rowCount()  # 获取行数
        for row in range(row_numb):
            if self.request_arguments_table.item(row, 0) and self.request_arguments_table.item(row, 1):
                key = self.request_arguments_table.item(row, 0).text().strip()  # 获取消息头的key值，并且去除字符串前后空格
                value = self.request_arguments_table.item(row, 1).text().strip()  # 获取消息头的value值，并且去除字符串前后空格
                headers[key] = value
        print(f'更新消息头为{headers}')
        return headers

    def machine_message_body(self):
        self.param = {}
        text = self.message_body.toPlainText()
        if text:
            for t in text.split('&'):
                t2 = []
                for t1 in t.split('='):
                    t2.append(t1)
                self.param[t2[0].strip()] = t2[1].strip()
        print(f'更新消息体为{self.param}')
        return self.param

    ##############   处理请求数据  ###########################################
    def create_thread(self):
        def send_request():
            # self.clean_message.clicked.connect(self.send_return_message.clear)  # 连接清除函数
            self.global_ms.response_start.emit()  # 发送线程开始的消息给“发送”按钮，进行置灰
            url = self.url_info
            headers = self.update_message_head()
            data = self.machine_message_body()
            if self.method_info == 'GET':
                response = self.whole_request.get(url, headers=headers, params=data)
            elif self.method_info == 'POST':
                response = self.whole_request.post(url, headers=headers, data=data)
            elif self.method_info == 'PUT':
                response = self.whole_request.put(url, headers=headers, data=data)
            else:
                response = self.whole_request.delete(url, headers=headers, data=data)
            # 处理相应数据
            result = f'------------发送请求------------\n'
            result += f'{self.method_info}    {self.url_info}\n'
            for name, value in headers.items():
                result += f'{name}   {value}\n'
            result += f'\n'
            result += f'{data}\n\n'
            result += f'------------得到响应------------\n'
            for header, value in response.headers.items():
                result += f'{header}  {value}\n'
            result += f'\n\n'
            result += f'状态码{response.status_code}\n\n\n'
            res = response.json()
            result += str(res)
            # try:
            #     for r in range(int(self.param['rn'])):
            #         code = res['Result']['list']['body'][r]['code']
            #         name = res['Result']['list']['body'][r]['name']
            #         result += f'股票名称：{name}  股票代码：{code}\n'
            # except KeyError as e:
            #     print(f"Missing key in response: {e}")

            self.global_ms.response_print.emit(self.send_return_message, result)
            self.global_ms.response_finish.emit()  # 发送线程开始的消息给“发送”按钮，进行启动

        t = Thread(target=send_request)
        t.start()

    #############   实现拖拽功能   ####################
    # 获取选中文本
    def get_slelect_text(self):
        select_text = self.input_url.selectedText()
        if select_text:
            self.pull_push_message.setText(select_text)
        else:
            pass


app = QApplication()
http_tool = HttpRequestTool()
http_tool.show()
app.exec()
